LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY sram_cntrl IS
	PORT (
		--from DE2 board
		clk_50		: IN STD_LOGIC;
		
		--from switchboard_cntrl
		reset_n		: IN STD_LOGIC;
		
		--FOR TEST
		test_req_n	: IN STD_LOGIC;
		
		--from RCV
		wr_req_n	: IN STD_LOGIC;
		framein		: IN STD_LOGIC_VECTOR(15 DOWNTO 0);
		
		--from XMT (or internal mem mgr ROM when writing)
		rd_req_n	: IN STD_LOGIC;
		mem_ptr		: IN STD_LOGIC_VECTOR(17 DOWNTO 0);
		
		--to RCV
		wr_ptr		: OUT STD_LOGIC_VECTOR(17 DOWNTO 0) := "00" & X"0000";
		
		--to XMT
		xmt_int		: OUT STD_LOGIC := '0';
		frameout	: OUT STD_LOGIC_VECTOR(15 DOWNTO 0) := X"0000";
		
		--to SRAM
		wr_en_n		: OUT STD_LOGIC := '1';
		out_en_n	: OUT STD_LOGIC := '0';
		ub_en_n		: OUT STD_LOGIC := '0';
		lb_en_n		: OUT STD_LOGIC := '0';
		chip_en_n	: OUT STD_LOGIC := '0';
		
		mem_addr	: OUT STD_LOGIC_VECTOR(17 DOWNTO 0) := "00" & X"0000";
		mem_data	: INOUT STD_LOGIC_VECTOR(15 DOWNTO 0)
	);
END sram_cntrl;
			
ARCHITECTURE Behavior OF sram_cntrl IS
	TYPE State_type IS (RCVwr, IDLE, XMTrd, TEST);
	TYPE test_data_array IS ARRAY(7 DOWNTO 0) OF STD_LOGIC_VECTOR(15 DOWNTO 0);
	TYPE test_addr_array IS ARRAY(7 DOWNTO 0) OF STD_LOGIC_VECTOR(17 DOWNTO 0);
	SIGNAL y : State_type := IDLE;
	SIGNAL test_data : test_data_array;
	SIGNAL test_addr : test_addr_array;
	SIGNAL test_index : INTEGER RANGE 0 TO 15;
	SIGNAL test_delay : STD_LOGIC_VECTOR(25 DOWNTO 0);
	SIGNAL test_en_n : STD_LOGIC := '1';
	SIGNAL int_wr_ptr : STD_LOGIC_VECTOR(17 DOWNTO 0);
	SIGNAL write_delay : STD_LOGIC;
--	SIGNAL data_buffer : STD_LOGIC_VECTOR(15 DOWNTO 0);
--	SIGNAL write_head : STD_LOGIC_VECTOR(17 DOWNTO 0);
--	SIGNAL write_tail : STD_LOGIC_VECTOR(17 DOWNTO 0);
BEGIN
	--wr_ptr <= int_wr_ptr;
	--mem_ptr <= write_head;
	wr_ptr <= int_wr_ptr;
	--define static test codes
	test_data(0) <= X"0001";
	test_data(1) <= X"0005";
	test_data(2) <= X"000F";
	test_data(3) <= X"00F0";
	test_data(4) <= X"0F00";
	test_data(5) <= X"F000";
	test_data(6) <= X"8000";
	test_data(7) <= X"AAAA";
	test_addr(0) <= "00" & X"0001"; --761d * 1d
	test_addr(1) <= "00" & X"0002"; --761d * 2d
	test_addr(2) <= "00" & X"0003"; --761d * 3d
	test_addr(3) <= "00" & X"0004"; --761d * 4d
	test_addr(4) <= "00" & X"0005"; --761d * 5d
	test_addr(5) <= "00" & X"0006"; --761d * 6d
	test_addr(6) <= "00" & X"0008"; --761d * 8d
	test_addr(7) <= "00" & X"000A"; --761d * 10d
	
	PROCESS (reset_n, clk_50)
	BEGIN
		IF reset_n = '0' THEN
			test_index <= 15;
			test_en_n <= '1';
			--init internal wr_ptr to end of mem (incr to 0 before 1st write)
			int_wr_ptr <= (OTHERS => '1');
			mem_data <= (OTHERS => 'Z');
			test_delay <= (OTHERS => '0');
			write_delay <= '0';
			--SRAM chip init to enabled read 16-bit mode
			wr_en_n	<= '1';
			out_en_n <= '0';
			ub_en_n <= '0';
			lb_en_n <= '0';
			chip_en_n <= '0';
			--init state
			y <= IDLE;
		ELSIF (clk_50'EVENT AND clk_50='1') THEN
			IF (y = IDLE) THEN
				mem_data <= (OTHERS => 'Z');
				test_delay <= (OTHERS => '0');
				write_delay <= '0';
				IF (test_en_n = '0') THEN
					IF (test_index = 7) THEN
						test_en_n <= '1';
					ELSE
						test_index <= (test_index + 1);
						xmt_int <= '1';
						y <= RCVwr;
					END IF;
				ELSIF (test_req_n = '0') THEN
					y <= TEST;
				ELSIF (wr_req_n = '0') THEN
					xmt_int <= '1';
					--int_wr_ptr <= (int_wr_ptr + 1); --incr to next write location
					--mem_addr <= mem_ptr;
					y <= RCVwr;
				ELSIF (rd_req_n = '0') THEN
					--mem_addr <= mem_ptr;
					y <= XMTrd;
				END IF;
			ELSIF (y = RCVwr) THEN
				wr_en_n <= '0'; --enable writing the SRAM
				IF (test_en_n = '0') THEN
					mem_addr <= test_addr(test_index);
					mem_data <= test_data(test_index);
				ELSE
					--mem_addr <= int_wr_ptr;
					mem_addr <= mem_ptr;
					mem_data <= framein;
				END IF;
				IF (write_delay = '1') THEN --X"2FAF080" = 1 sec@50MHz
					wr_en_n <= '1'; --disable writing to the SRAM
					xmt_int <= '0';
					y <= IDLE;
				ELSE
					write_delay <= '1';
				END IF;
			ELSIF (y = XMTrd) THEN
				wr_en_n <= '1';
				mem_addr <= mem_ptr;
				frameout <= mem_data;
				IF (test_req_n = '1') THEN
					xmt_int <= '0';
					y <= IDLE;
				END IF;
			ELSIF (y = TEST) THEN
				IF (test_delay = X"2") THEN --X"2FAF080" = 1 sec@50MHz
					test_index <= 15;
					test_en_n <= '0';
					y <= IDLE;
				ELSE
					test_delay <= test_delay + 1;
				END IF;
			END IF;
		END IF;
	END PROCESS;
END Behavior;